<!DOCTYPE html>
<html >
<head>

    <!--[if lt IE 9]>
        <style>body {display: none; background: none !important} </style>
        <meta http-equiv="Refresh" Content="0; url=//outdatedbrowser.com/" />
    <![endif]-->

<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<meta name="format-detection" content="telephone=no" />
<meta name="author" content="xiaoyou" />



<meta name="description" content="Java8是2014年发布的，至今也已经有快三年的时间了，之前虽然有学习过，但是学的比较零散，不成系统，而且也没有覆盖到Java8所有的特性。 由于公司已经使用了JDK1.8，所以工作中能使用Java8的机会还是很多的，因此决定来系统地学习一下Java8的新特性，这是对我最近学习Java8的一些记录， 以备在有些细节记不太清的时候可以查询。">
<meta name="keywords" content="Java8">
<meta property="og:type" content="article">
<meta property="og:title" content="Java8学习笔记">
<meta property="og:url" content="http://yoursite.com/2017/04/26/java-8-in-practice/index.html">
<meta property="og:site_name" content="Lost Youth">
<meta property="og:description" content="Java8是2014年发布的，至今也已经有快三年的时间了，之前虽然有学习过，但是学的比较零散，不成系统，而且也没有覆盖到Java8所有的特性。 由于公司已经使用了JDK1.8，所以工作中能使用Java8的机会还是很多的，因此决定来系统地学习一下Java8的新特性，这是对我最近学习Java8的一些记录， 以备在有些细节记不太清的时候可以查询。">
<meta property="og:image" content="http://oo77gy3uq.bkt.clouddn.com/Java8-features.png">
<meta property="og:updated_time" content="2017-04-26T06:06:30.000Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Java8学习笔记">
<meta name="twitter:description" content="Java8是2014年发布的，至今也已经有快三年的时间了，之前虽然有学习过，但是学的比较零散，不成系统，而且也没有覆盖到Java8所有的特性。 由于公司已经使用了JDK1.8，所以工作中能使用Java8的机会还是很多的，因此决定来系统地学习一下Java8的新特性，这是对我最近学习Java8的一些记录， 以备在有些细节记不太清的时候可以查询。">
<meta name="twitter:image" content="http://oo77gy3uq.bkt.clouddn.com/Java8-features.png">

<link rel="apple-touch-icon" href= "/apple-touch-icon.png">


    <link rel="alternate" href="/atom.xml" title="Lost Youth" type="application/atom+xml">



    <link rel="shortcut icon" href="/favicon.png">



    <link href="//cdn.bootcss.com/animate.css/3.5.1/animate.min.css" rel="stylesheet">



    <link href="//cdn.bootcss.com/fancybox/2.1.5/jquery.fancybox.min.css" rel="stylesheet">



    <script src="//cdn.bootcss.com/pace/1.0.2/pace.min.js"></script>
    <link href="//cdn.bootcss.com/pace/1.0.2/themes/blue/pace-theme-minimal.css" rel="stylesheet">


<link rel="stylesheet" href="/css/style.css">



<link href="//cdn.bootcss.com/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet">


<title>Java8学习笔记 | Lost Youth</title>

<script src="//cdn.bootcss.com/jquery/2.2.4/jquery.min.js"></script>
<script src="//cdn.bootcss.com/clipboard.js/1.5.10/clipboard.min.js"></script>

<script>
    var yiliaConfig = {
        fancybox: true,
        animate: true,
        isHome: false,
        isPost: true,
        isArchive: false,
        isTag: false,
        isCategory: false,
        fancybox_js: "//cdn.bootcss.com/fancybox/2.1.5/jquery.fancybox.min.js",
        scrollreveal: "//cdn.bootcss.com/scrollReveal.js/3.1.4/scrollreveal.min.js",
        search: undefined
    }
</script>


    <script> yiliaConfig.jquery_ui = [false]; </script>



    <script> yiliaConfig.rootUrl = "\/";</script>






</head>
<body>
  <div id="container">
    <div class="left-col">
    <div class="overlay"></div>
<div class="intrude-less">
    <header id="header" class="inner">
        <a href="/" class="profilepic">
            <img src="/img/avatar.png" class="animated zoomIn">
        </a>
        <hgroup>
          <h1 class="header-author"><a href="/">xiaoyou</a></h1>
        </hgroup>

        

        


        
            <div id="switch-btn" class="switch-btn">
                <div class="icon">
                    <div class="icon-ctn">
                        <div class="icon-wrap icon-house" data-idx="0">
                            <div class="birdhouse"></div>
                            <div class="birdhouse_holes"></div>
                        </div>
                        <div class="icon-wrap icon-ribbon hide" data-idx="1">
                            <div class="ribbon"></div>
                        </div>
                        
                        <div class="icon-wrap icon-link hide" data-idx="2">
                            <div class="loopback_l"></div>
                            <div class="loopback_r"></div>
                        </div>
                        
                        
                        <div class="icon-wrap icon-me hide" data-idx="3">
                            <div class="user"></div>
                            <div class="shoulder"></div>
                        </div>
                        
                    </div>
                    
                </div>
                <div class="tips-box hide">
                    <div class="tips-arrow"></div>
                    <ul class="tips-inner">
                        <li>菜单</li>
                        <li>标签</li>
                        
                        <li>友情链接</li>
                        
                        
                        <li>关于我</li>
                        
                    </ul>
                </div>
            </div>
        

        <div id="switch-area" class="switch-area">
            <div class="switch-wrap">
                <section class="switch-part switch-part1">
                    <nav class="header-menu">
                        <ul>
                        
                            <li><a href="/">Home</a></li>
                        
                            <li><a href="/archives">Archives</a></li>
                        
                            <li><a href="/tools">Tools</a></li>
                        
                            <li><a href="/about">About</a></li>
                        
                        </ul>
                    </nav>
                    <nav class="header-nav">
                        <ul class="social">
                            
                                <a class="fa Email" href="mailto:123@123.com" title="Email"></a>
                            
                                <a class="fa GitHub" href="#" title="GitHub"></a>
                            
                                <a class="fa RSS" href="/atom.xml" title="RSS"></a>
                            
                        </ul>
                    </nav>
                </section>
                
                
                <section class="switch-part switch-part2">
                    <div class="widget tagcloud" id="js-tagcloud">
                        <ul class="tag-list"><li class="tag-list-item"><a class="tag-list-link" href="/tags/Git/">Git</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Java8/">Java8</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/MySql/">MySql</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/RocketMQ/">RocketMQ</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Spring-Boot/">Spring Boot</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Tomcat/">Tomcat</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/分布式-服务化/">分布式 服务化</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/唯一ID/">唯一ID</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/微服务/">微服务</a></li></ul>
                    </div>
                </section>
                
                
                
                <section class="switch-part switch-part3">
                    <div id="js-friends">
                    
                      <a class="main-nav-link switch-friends-link" href="https://hexo.io">Hexo</a>
                    
                      <a class="main-nav-link switch-friends-link" href="https://pages.github.com/">GitHub</a>
                    
                      <a class="main-nav-link switch-friends-link" href="http://moxfive.xyz/">MOxFIVE</a>
                    
                    </div>
                </section>
                

                
                
                <section class="switch-part switch-part4">
                
                    <div id="js-aboutme">Man</div>
                </section>
                
            </div>
        </div>
    </header>                
</div>
    </div>
    <div class="mid-col">
      <nav id="mobile-nav">
      <div class="overlay">
          <div class="slider-trigger"></div>
          <h1 class="header-author js-mobile-header hide"><a href="/" title="回到主页">xiaoyou</a></h1>
      </div>
    <div class="intrude-less">
        <header id="header" class="inner">
            <a href="/" class="profilepic">
                <img src="/img/avatar.png" class="animated zoomIn">
            </a>
            <hgroup>
              <h1 class="header-author"><a href="/" title="回到主页">xiaoyou</a></h1>
            </hgroup>
            
            <nav class="header-menu">
                <ul>
                
                    <li><a href="/">Home</a></li>
                
                    <li><a href="/archives">Archives</a></li>
                
                    <li><a href="/tools">Tools</a></li>
                
                    <li><a href="/about">About</a></li>
                
                <div class="clearfix"></div>
                </ul>
            </nav>
            <nav class="header-nav">
                        <ul class="social">
                            
                                <a class="fa Email" target="_blank" href="mailto:123@123.com" title="Email"></a>
                            
                                <a class="fa GitHub" target="_blank" href="#" title="GitHub"></a>
                            
                                <a class="fa RSS" target="_blank" href="/atom.xml" title="RSS"></a>
                            
                        </ul>
            </nav>
        </header>                
    </div>
    <link class="menu-list" tags="标签" friends="友情链接" about="关于我"/>
</nav>
      <div class="body-wrap"><article id="post-java-8-in-practice" class="article article-type-post" itemscope itemprop="blogPost">
  
    <div class="article-meta">
      <a href="/2017/04/26/java-8-in-practice/" class="article-date">
      <time datetime="2017-04-26T00:50:00.000Z" itemprop="datePublished">2017-04-26</time>
</a>


    </div>
  
  <div class="article-inner">
    
      <input type="hidden" class="isFancy" />
    
    
      <header class="article-header">
        
  
    <h1 class="article-title" itemprop="name">
      Java8学习笔记
    </h1>
  

      </header>
      
      <div class="article-info article-info-post">
        

        
    <div class="article-tag tagcloud">
        <ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Java8/">Java8</a></li></ul>
    </div>

        <div class="clearfix"></div>
      </div>
      
    
    <div class="article-entry" itemprop="articleBody">
      
          
        <p>原文出处： <a href="http://listenzhangbin.com/post/2017/01/java8-learning-notes/" target="_blank" rel="external">Listen</a></p>
<p>Java8是2014年发布的，至今也已经有快三年的时间了，之前虽然有学习过，但是学的比较零散，不成系统，而且也没有覆盖到Java8所有的特性。 由于公司已经使用了JDK1.8，所以工作中能使用Java8的机会还是很多的，因此决定来系统地学习一下Java8的新特性，这是对我最近学习Java8的一些记录， 以备在有些细节记不太清的时候可以查询。</p>
<p><img src="http://oo77gy3uq.bkt.clouddn.com/Java8-features.png" alt="Java8"></p>
<p>先来一个概览，上图是我整理的Java8中的新特性，总的来看，大致上可以分成这么几个大块。</p>
<h2 id="函数式接口"><a href="#函数式接口" class="headerlink" title="函数式接口"></a>函数式接口</h2><p>所谓的函数式接口就是只有一个抽象方法的接口，注意这里说的是抽象方法，因为Java8中加入了默认方法的特性，但是函数式接口是不关心接口中有没有默认方法的。 一般函数式接口可以使用<code>@FunctionalInterface</code>注解的形式来标注表示这是一个函数式接口，该注解标注与否对函数式接口没有实际的影响， 不过一般还是推荐使用该注解，就像使用<code>@Override</code>注解一样。JDK1.8中提供了一些函数式接口如下：</p>
<table>
<thead>
<tr>
<th style="text-align:center">函数式接口</th>
<th style="text-align:center">函数描述符</th>
<th style="text-align:center">原始类型特化</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center"><code>Predicate&lt;T&gt;</code></td>
<td style="text-align:center">T -&gt; boolean</td>
<td style="text-align:center"><code>IntPredicate, LongPredicate, DoublePredicate</code></td>
</tr>
<tr>
<td style="text-align:center"><code>Consumer&lt;T&gt;</code></td>
<td style="text-align:center">T -&gt; void</td>
<td style="text-align:center"><code>IntConsumer, LongConsumer, DoubleConsumer</code></td>
</tr>
<tr>
<td style="text-align:center"><code>Function&lt;T,R&gt;</code></td>
<td style="text-align:center">T -&gt; R</td>
<td style="text-align:center"><code>IntFunction&lt;R&gt;, IntToDoubleFunction, IntToLongFunction,  LongFunction&lt;R&gt;, LongToDoubleFunction, LongToIntFunction,  DoubleFunction&lt;R&gt;, ToIntFunction&lt;T&gt;, ToDoubleFunction&lt;T&gt;,  ToLongFunction&lt;T&gt;</code></td>
</tr>
<tr>
<td style="text-align:center"><code>Supplier&lt;T&gt;</code></td>
<td style="text-align:center">() -&gt; T</td>
<td style="text-align:center"><code>BooleanSupplier, IntSupplier, LongSupplier, DoubleSupplier</code></td>
</tr>
<tr>
<td style="text-align:center"><code>UnaryOperator&lt;T&gt;</code></td>
<td style="text-align:center">T -&gt; T</td>
<td style="text-align:center"><code>IntUnaryOperator, LongUnaryOperator, DoubleUnaryOperator</code></td>
</tr>
<tr>
<td style="text-align:center"><code>BinaryOperator&lt;T&gt;</code></td>
<td style="text-align:center">(T,T) -&gt; T</td>
<td style="text-align:center"><code>IntBinaryOperator, LongBinaryOperator, DoubleBinaryOperator</code></td>
</tr>
<tr>
<td style="text-align:center"><code>BiPredicate&lt;L,R&gt;</code></td>
<td style="text-align:center">(L,R) -&gt; boolean</td>
<td style="text-align:center"></td>
</tr>
<tr>
<td style="text-align:center"><code>BiConsumer&lt;T,U&gt;</code></td>
<td style="text-align:center">(T,U) -&gt; void</td>
<td style="text-align:center"><code>ObjIntConsumer&lt;T&gt;, ObjLongConsumer&lt;T&gt;, ObjDoubleConsumer&lt;T&gt;</code></td>
</tr>
<tr>
<td style="text-align:center"><code>BiFunction&lt;T,U,R&gt;</code></td>
<td style="text-align:center">(T,U) -&gt; R</td>
<td style="text-align:center"><code>ToIntBiFunction&lt;T,U&gt;, ToLongBiFunction&lt;T,U&gt;, ToDoubleBiFunction&lt;T,U&gt;</code></td>
</tr>
</tbody>
</table>
<p>上表中的原始类型特化指的是为了消除自动装箱和拆箱的性能开销，JDK1.8提供的针对基本类型的函数式接口。</p>
<h2 id="Lambda表达式和方法引用"><a href="#Lambda表达式和方法引用" class="headerlink" title="Lambda表达式和方法引用"></a>Lambda表达式和方法引用</h2><p>有了函数式接口之后，就可以使用Lambda表达式和方法引用了。其实函数式接口的表中的函数描述符就是Lambda表达式，在函数式接口中Lambda表达式相当于匿名内部类的效果。 举个简单的例子：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestLambda</span> </span>&#123;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">execute</span><span class="params">(Runnable runnable)</span> </span>&#123;</div><div class="line"></div><div class="line">runnable.run();</div><div class="line"></div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</div><div class="line"></div><div class="line"><span class="comment">//Java8之前</span></div><div class="line"></div><div class="line">execute(<span class="keyword">new</span> Runnable() &#123;</div><div class="line"></div><div class="line"><span class="meta">@Override</span></div><div class="line"></div><div class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</div><div class="line"></div><div class="line">		System.out.println(<span class="string">"run"</span>);</div><div class="line"></div><div class="line">	&#125;</div><div class="line"></div><div class="line">&#125;);</div><div class="line"></div><div class="line"><span class="comment">//使用Lambda表达式</span></div><div class="line"></div><div class="line">execute(() -&gt; System.out.println(<span class="string">"run"</span>));</div><div class="line"></div><div class="line">	&#125;</div><div class="line"></div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>可以看到，相比于使用匿名内部类的方式，Lambda表达式可以使用更少的代码但是有更清晰的表述。注意，Lambda表达式也不是完全等价于匿名内部类的， 两者的不同点在于<code>this</code>的指向和本地变量的屏蔽上。</p>
<p>Lambda表达式还可以复合，把几个Lambda表达式串起来使用：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">Predicate&lt;Apple&gt; redAndHeavyApple = redApple.and(a -&gt; a.getWeight() &gt; <span class="number">150</span>).or(a -&gt; “green”.equals(a.getColor()));</div></pre></td></tr></table></figure>
<p>上面这行代码把两个Lambda表达式串了起来，含义是选择重量大于150或者绿色的苹果。</p>
<p>方法引用可以看作Lambda表达式的更简洁的一种表达形式，使用<code>::</code>操作符，方法引用主要有三类：</p>
<ol>
<li>指向静态方法的方法引用(例如Integer的parseInt方法，写作<code>Integer::parseInt</code>)；</li>
<li>指向任意类型实例方法的方法引用(例如String的length方法，写作<code>String::length</code>)；</li>
<li>指向现有对象的实例方法的方法引用(例如假设你有一个本地变量localVariable用于存放Variable类型的对象，它支持实例方法getValue，那么可以写成<code>localVariable::getValue</code>)。</li>
</ol>
<p>举个方法引用的简单的例子：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">Function&lt;String, Integer&gt; stringToInteger = (String s) -&gt; Integer.parseInt(s);</div><div class="line"> </div><div class="line"><span class="comment">//使用方法引用</span></div><div class="line">Function&lt;String, Integer&gt; stringToInteger = Integer::parseInt;</div></pre></td></tr></table></figure>
<p>方法引用中还有一种特殊的形式，构造函数引用，假设一个类有一个默认的构造函数，那么使用方法引用的形式为：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">Supplier&lt;SomeClass&gt; c1 = SomeClass::<span class="keyword">new</span>;</div><div class="line">SomeClass s1 = c1.get();</div><div class="line"> </div><div class="line"><span class="comment">//等价于</span></div><div class="line"> </div><div class="line">Supplier&lt;SomeClass&gt; c1 = () -&gt; <span class="keyword">new</span> SomeClass();</div><div class="line">SomeClass s1 = c1.get();</div></pre></td></tr></table></figure>
<p>如果是构造函数有一个参数的情况：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"></div><div class="line">Function&lt;Integer, SomeClass&gt; c1 = SomeClass::<span class="keyword">new</span>;</div><div class="line">SomeClass s1 = c1.apply(<span class="number">100</span>);</div><div class="line"> </div><div class="line"><span class="comment">//等价于</span></div><div class="line"> </div><div class="line">Function&lt;Integer, SomeClass&gt; c1 = i -&gt; <span class="keyword">new</span> SomeClass(i);</div><div class="line">SomeClass s1 = c1.apply(<span class="number">100</span>);</div></pre></td></tr></table></figure>
<h2 id="Stream"><a href="#Stream" class="headerlink" title="Stream"></a>Stream</h2><p>Stream可以分成串行流和并行流，并行流是基于Java7中提供的<code>ForkJoinPool</code>来进行任务的调度，达到并行的处理的目的。 集合是我们平时在进行Java编程时非常常用的API，使用Stream可以帮助更好的来操作集合。Stream提供了非常丰富的操作，包括筛选、切片、映射、查找、匹配、归约等等， 这些操作又可以分为中间操作和终端操作，中间操作会返回一个流，因此我们可以使用多个中间操作来作链式的调用，当使用了终端操作之后，那么这个流就被认为是被消费了， 每个流只能有一个终端操作。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//筛选后收集到一个List中</span></div><div class="line">List&lt;Apple&gt; vegetarianMenu = apples.stream().filter(Apple::isRed).collect(Collectors.toList());</div><div class="line"> </div><div class="line"><span class="comment">//筛选加去重</span></div><div class="line">List&lt;Integer&gt; numbers = Arrays.asList(<span class="number">1</span>,<span class="number">2</span>,<span class="number">1</span>,<span class="number">3</span>,<span class="number">3</span>,<span class="number">2</span>,<span class="number">4</span>);</div><div class="line">numbers.stream().filter(i -&gt; i % <span class="number">2</span> == <span class="number">0</span>).distinct().forEach(System.out::println);</div></pre></td></tr></table></figure>
<p>以上都是一些简单的例子，Stream提供的API非常丰富，可以很好的满足我们的需求。</p>
<table>
<thead>
<tr>
<th style="text-align:center">操作</th>
<th style="text-align:center">类型</th>
<th style="text-align:center">返回类型</th>
<th style="text-align:center">使用的类型/函数式接口</th>
<th style="text-align:center">函数描述符</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">filter</td>
<td style="text-align:center">中间</td>
<td style="text-align:center"><code>Stream&lt;T&gt;</code></td>
<td style="text-align:center"><code>Predicate&lt;T&gt;</code></td>
<td style="text-align:center"><code>T -&gt; boolean</code></td>
</tr>
<tr>
<td style="text-align:center">distinct</td>
<td style="text-align:center">中间</td>
<td style="text-align:center"><code>Stream&lt;T&gt;</code></td>
<td style="text-align:center"></td>
<td style="text-align:center"></td>
</tr>
<tr>
<td style="text-align:center">skip</td>
<td style="text-align:center">中间</td>
<td style="text-align:center"><code>Stream&lt;T&gt;</code></td>
<td style="text-align:center"><code>long</code></td>
<td style="text-align:center"></td>
</tr>
<tr>
<td style="text-align:center">limit</td>
<td style="text-align:center">中间</td>
<td style="text-align:center"><code>Stream&lt;T&gt;</code></td>
<td style="text-align:center"><code>long</code></td>
<td style="text-align:center"></td>
</tr>
<tr>
<td style="text-align:center">map</td>
<td style="text-align:center">中间</td>
<td style="text-align:center"><code>Stream&lt;R&gt;</code></td>
<td style="text-align:center"><code>Function&lt;T,R&gt;</code></td>
<td style="text-align:center"><code>T -&gt; R</code></td>
</tr>
<tr>
<td style="text-align:center">flatMap</td>
<td style="text-align:center">中间</td>
<td style="text-align:center"><code>Stream&lt;R&gt;</code></td>
<td style="text-align:center"><code>Function&lt;T, Stream&lt;R&gt;&gt;</code></td>
<td style="text-align:center"><code>T -&gt; Stream&lt;R&gt;</code></td>
</tr>
<tr>
<td style="text-align:center">sorted</td>
<td style="text-align:center">中间</td>
<td style="text-align:center"><code>Stream&lt;R&gt;</code></td>
<td style="text-align:center"><code>Comparator&lt;T&gt;</code></td>
<td style="text-align:center"><code>(T,T) -&gt; int</code></td>
</tr>
<tr>
<td style="text-align:center">anyMatch</td>
<td style="text-align:center">终端</td>
<td style="text-align:center"><code>boolean</code></td>
<td style="text-align:center"><code>Predicate&lt;T&gt;</code></td>
<td style="text-align:center"><code>T -&gt; boolean</code></td>
</tr>
<tr>
<td style="text-align:center">noneMatch</td>
<td style="text-align:center">终端</td>
<td style="text-align:center"><code>boolean</code></td>
<td style="text-align:center"><code>Predicate&lt;T&gt;</code></td>
<td style="text-align:center"><code>T -&gt; boolean</code></td>
</tr>
<tr>
<td style="text-align:center">allMatch</td>
<td style="text-align:center">终端</td>
<td style="text-align:center"><code>boolean</code></td>
<td style="text-align:center"><code>Predicate&lt;T&gt;</code></td>
<td style="text-align:center"><code>T -&gt; boolean</code></td>
</tr>
<tr>
<td style="text-align:center">findAny</td>
<td style="text-align:center">终端</td>
<td style="text-align:center"><code>Optional&lt;T&gt;</code></td>
<td style="text-align:center"></td>
<td style="text-align:center"></td>
</tr>
<tr>
<td style="text-align:center">findFirst</td>
<td style="text-align:center">终端</td>
<td style="text-align:center"><code>Optional&lt;T&gt;</code></td>
<td style="text-align:center"></td>
<td style="text-align:center"></td>
</tr>
<tr>
<td style="text-align:center">forEach</td>
<td style="text-align:center">终端</td>
<td style="text-align:center"><code>void</code></td>
<td style="text-align:center"><code>Consumer&lt;T&gt;</code></td>
<td style="text-align:center"><code>T -&gt; void</code></td>
</tr>
<tr>
<td style="text-align:center">collect</td>
<td style="text-align:center">终端</td>
<td style="text-align:center"><code>R</code></td>
<td style="text-align:center"><code>Collector&lt;T,A,R&gt;</code></td>
<td style="text-align:center"></td>
</tr>
<tr>
<td style="text-align:center">reduce</td>
<td style="text-align:center">终端</td>
<td style="text-align:center"><code>Optional&lt;T&gt;</code></td>
<td style="text-align:center"><code>BinaryOperator&lt;T&gt;</code></td>
<td style="text-align:center"><code>(T,T) -&gt; T</code></td>
</tr>
<tr>
<td style="text-align:center">count</td>
<td style="text-align:center">终端</td>
<td style="text-align:center"><code>long</code></td>
<td style="text-align:center"></td>
</tr>
</tbody>
</table>
<p>与函数式接口类似，Stream也提供了原始类型特化的流，比如说<code>IntStream</code>等：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//maoToInt转化为一个IntStream</span></div><div class="line"><span class="keyword">int</span> count = list.stream().mapToInt(list::getNumber).sum();</div></pre></td></tr></table></figure>
<p>并行流与串行流的区别就在于将stream改成parallelStream，并行流会将流的操作拆分，放到线程池中去执行，但是并不是说使用并行流的性能一定好于串行的流， 恰恰相反，可能大多数时候使用串行流会有更好的性能，这是因为将任务提交到线程池，执行完之后再合并，这些本身都是有不小的开销的。关于并行流其实还有非常多的细节， 这里做一个抛砖引玉，有兴趣的同学可以在网上自行查找一些资料来学习。</p>
<h2 id="默认方法"><a href="#默认方法" class="headerlink" title="默认方法"></a>默认方法</h2><p>默认方法出现的原因是为了对原有接口的扩展，有了默认方法之后就不怕因改动原有的接口而对已经使用这些接口的程序造成的代码不兼容的影响。 在Java8中也对一些接口增加了一些默认方法，比如<code>Map</code>接口等等。一般来说，使用默认方法的场景有两个：可选方法和行为的多继承。</p>
<p>默认方法的使用相对来说比较简单，唯一要注意的点是如何处理默认方法的冲突。关于如何处理默认方法的冲突可以参考以下三条规则：</p>
<ol>
<li>类中的方法优先级最高。类或父类中声明的方法的优先级高于任何声明为默认方法的优先级。</li>
<li>如果无法依据第一条规则进行判断，那么子接口的优先级更高：函数签名相同时，优先选择拥有最具体实现的默认方法的接口。即如果B继承了A，那么B就比A更具体。</li>
<li>最后，如果还是无法判断，继承了多个接口的类必须通过显式覆盖和调用期望的方法，显式地选择使用哪一个默认方法的实现。那么如何显式地指定呢:</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">C</span> <span class="keyword">implements</span> <span class="title">B</span>, <span class="title">A</span> </span>&#123;</div><div class="line"> </div><div class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">hello</span><span class="params">()</span> </span>&#123;</div><div class="line">        B.<span class="keyword">super</span>().hello();    </div><div class="line">    &#125;</div><div class="line"> </div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>使用<code>X.super.m(..)</code>显式地调用希望调用的方法。</p>
<h2 id="Optional"><a href="#Optional" class="headerlink" title="Optional"></a>Optional</h2><p>如果一个方法返回一个Object，那么我们在使用的时候总是要判断一下返回的结果是否为空，一般是这样的形式：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">if</span> (a != <span class="keyword">null</span>) &#123;</div><div class="line">    <span class="comment">//do something...</span></div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>但是简单的情况还好，如果复杂的情况下每一个都要去检查非常麻烦，而且写出来的代码也不好看、很臃肿，但是如果不检查就很容易遇到<code>NullPointerException</code>， Java8中的Optional就是为此而设计的。</p>
<p>Optional一般使用在方法的返回值中，如果使用Optional来包装方法的返回值，这就表示方法的返回值可能为<code>null</code>，需要使用Optional提供的方法来检查，如果为null，还可以提供一个默认值。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//创建Optional对象</span></div><div class="line">Optional&lt;String&gt; opt = Optional.empty();</div><div class="line"> </div><div class="line"><span class="comment">//依据一个非空值创建Optional</span></div><div class="line">Optional&lt;String&gt; opt = Optional.of(<span class="string">"hello"</span>);</div><div class="line"> </div><div class="line"><span class="comment">//可接受null的Optional</span></div><div class="line">Optional&lt;String&gt; opt = Optional.ofNullable(<span class="keyword">null</span>);</div></pre></td></tr></table></figure>
<p>除了以上这些方法外，Optional还提供了以下方法：</p>
<table>
<thead>
<tr>
<th style="text-align:center">方法</th>
<th style="text-align:center">描述</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">empty</td>
<td style="text-align:center">返回一个空的Optional实例</td>
</tr>
<tr>
<td style="text-align:center">filter</td>
<td style="text-align:center">如果值存在并且满足提供的谓词，就返回包括该值的Optional对象；否则返回一个空的Optional对象</td>
</tr>
<tr>
<td style="text-align:center">flatMap</td>
<td style="text-align:center">如果值存在，就对该值执行提供的mapping函数调用，返回一个Optional类型的值，否则就返回一个空的Optional对象</td>
</tr>
<tr>
<td style="text-align:center">get</td>
<td style="text-align:center">如果该值存在，将该值用Optional封装返回，否则抛出一个NoSuchElementException异常</td>
</tr>
<tr>
<td style="text-align:center">ifPresent</td>
<td style="text-align:center">如果值存在，就执行使用该值的方法调用，否则返回false</td>
</tr>
<tr>
<td style="text-align:center">isPresent</td>
<td style="text-align:center">如果值存在就返回true，否则返回false</td>
</tr>
<tr>
<td style="text-align:center">map</td>
<td style="text-align:center">如果值存在，就对该值执行提供的mapping函数调用</td>
</tr>
<tr>
<td style="text-align:center">of</td>
<td style="text-align:center">将指定值用Optional封装之后返回，如果该值为null，抛出一个NullPointerException异常</td>
</tr>
<tr>
<td style="text-align:center">ofNullable</td>
<td style="text-align:center">将指定值用Optional封装之后返回，如果该值为null，则返回一个空的Optional对象</td>
</tr>
<tr>
<td style="text-align:center">orElse</td>
<td style="text-align:center">如果有值则将其返回，否则返回一个默认值</td>
</tr>
<tr>
<td style="text-align:center">orElseGet</td>
<td style="text-align:center">如果有值则将其返回，否则返回一个由指定的Supplier接口生成的值</td>
</tr>
<tr>
<td style="text-align:center">orElseThrow</td>
<td style="text-align:center">如果有值则将其返回，否则抛出一个由指定的Supplier接口生成的异常</td>
</tr>
</tbody>
</table>
<h2 id="CompletableFuture"><a href="#CompletableFuture" class="headerlink" title="CompletableFuture"></a>CompletableFuture</h2><p>在Java8之前，我们会使用JDK提供的<code>Future</code>接口来进行一些异步的操作，其实<code>CompletableFuture</code>也是实现了<code>Future</code>接口， 并且基于<code>ForkJoinPool</code>来执行任务，因此本质上来讲，<code>CompletableFuture</code>只是对原有API的封装， 而使用CompletableFuture与原来的Future的不同之处在于可以将两个Future组合起来，或者如果两个Future是有依赖关系的，可以等第一个执行完毕后再实行第二个等特性。</p>
<p>先来看看基本的使用方式：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">public</span> Future&lt;Double&gt; <span class="title">getPriceAsync</span><span class="params">(<span class="keyword">final</span> String product)</span> </span>&#123;</div><div class="line">    <span class="keyword">final</span> CompletableFuture&lt;Double&gt; futurePrice = <span class="keyword">new</span> CompletableFuture&lt;&gt;();</div><div class="line">    <span class="keyword">new</span> Thread(() -&gt; &#123;</div><div class="line">        <span class="keyword">double</span> price = calculatePrice(product);</div><div class="line">        futurePrice.complete(price);  <span class="comment">//完成后使用complete方法，设置future的返回值</span></div><div class="line">    &#125;).start();</div><div class="line">    <span class="keyword">return</span> futurePrice;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>得到Future之后就可以使用get方法来获取结果，CompletableFuture提供了一些工厂方法来简化这些API，并且使用函数式编程的方式来使用这些API，例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">Future&lt;Double&gt; price = CompletableFuture.supplyAsync(() -&gt; calculatePrice(product));</div></pre></td></tr></table></figure>
<p>代码是不是一下子简洁了许多呢。之前说了，CompletableFuture可以组合多个Future，不管是Future之间有依赖的，还是没有依赖的。 如果第二个请求依赖于第一个请求的结果，那么可以使用<code>thenCompose</code>方法来组合两个Future</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"></div><div class="line"><span class="function"><span class="keyword">public</span> List&lt;String&gt; <span class="title">findPriceAsync</span><span class="params">(String product)</span> </span>&#123;</div><div class="line">    List&lt;CompletableFutute&lt;String&gt;&gt; priceFutures = tasks.stream()</div><div class="line">    .map(task -&gt; CompletableFuture.supplyAsync(() -&gt; task.getPrice(product),executor))</div><div class="line">    .map(future -&gt; future.thenApply(Work::parse))</div><div class="line">    .map(future -&gt; future.thenCompose(work -&gt; CompletableFuture.supplyAsync(() -&gt; Count.applyCount(work), executor)))</div><div class="line">    .collect(Collectors.toList());</div><div class="line"> </div><div class="line">    <span class="keyword">return</span> priceFutures.stream().map(CompletableFuture::join).collect(Collectors.toList());</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>上面这段代码使用了<code>thenCompose</code>来组合两个CompletableFuture。<code>supplyAsync</code>方法第二个参数接受一个自定义的Executor。 首先使用CompletableFuture执行一个任务，调用<code>getPrice</code>方法，得到一个Future，之后使用<code>thenApply</code>方法，将Future的结果应用<code>parse</code>方法， 之后再使用执行完<code>parse</code>之后的结果作为参数再执行一个<code>applyCount</code>方法，然后收集成一个<code>CompletableFuture&lt;String&gt;</code>的List， 最后再使用一个流，调用CompletableFuture的<code>join</code>方法，这是为了等待所有的异步任务执行完毕，获得最后的结果。</p>
<p>注意，这里必须使用两个流，如果在一个流里调用<code>join</code>方法，那么由于Stream的延迟特性，所有的操作还是会串行的执行，并不是异步的。</p>
<p>再来看一个两个Future之间没有依赖关系的例子：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">Future&lt;String&gt; futurePriceInUsd = CompletableFuture.supplyAsync(() -&gt; shop.getPrice(“price1”))</div><div class="line">                                    .thenCombine(CompletableFuture.supplyAsync(() -&gt; shop.getPrice(“price2”)), (s1, s2) -&gt; s1 + s2);</div></pre></td></tr></table></figure>
<p>这里有两个异步的任务，使用<code>thenCombine</code>方法来组合两个Future，<code>thenCombine</code>方法的第二个参数就是用来合并两个Future方法返回值的操作函数。</p>
<p>有时候，我们并不需要等待所有的异步任务结束，只需要其中的一个完成就可以了，CompletableFuture也提供了这样的方法：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//假设getStream方法返回一个Stream&lt;CompletableFuture&lt;String&gt;&gt;</span></div><div class="line">CompletableFuture[] futures = getStream(“listen”).map(f -&gt; f.thenAccept(System.out::println)).toArray(CompletableFuture[]::<span class="keyword">new</span>);</div><div class="line"><span class="comment">//等待其中的一个执行完毕</span></div><div class="line">CompletableFuture.anyOf(futures).join();</div></pre></td></tr></table></figure>
<p>使用<code>anyOf</code>方法来响应CompletableFuture的completion事件。</p>
<h2 id="新的时间和日期API"><a href="#新的时间和日期API" class="headerlink" title="新的时间和日期API"></a>新的时间和日期API</h2><p>Java8之前的时间和日期API并不好用，而且在线程安全性等方面也存在问题，一般会借助一些开源类库来解决时间处理的问题。在JDK1.8中新加入了时间和日期的API， 借助这些新的API基本可以不再需要开源类库的帮助来完成时间的处理了。</p>
<p>Java8中加入了<code>LocalDateTime, LocalDate, LocalTime, Duration, Period, Instant, DateTimeFormatter</code>等等API，来看一些使用这些API的简单的例子：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//创建日期</span></div><div class="line">LocalDate date = LocalDate.of(<span class="number">2017</span>,<span class="number">1</span>,<span class="number">21</span>); <span class="comment">//2017-01-21</span></div><div class="line"><span class="keyword">int</span> year = date.getYear() <span class="comment">//2017</span></div><div class="line">Month month = date.getMonth(); <span class="comment">//JANUARY</span></div><div class="line"><span class="keyword">int</span> day = date.getDayOfMonth(); <span class="comment">//21</span></div><div class="line">DayOfWeek dow = date.getDayOfWeek(); <span class="comment">//SATURDAY</span></div><div class="line"><span class="keyword">int</span> len = date.lengthOfMonth(); <span class="comment">//31(days in January)</span></div><div class="line"><span class="keyword">boolean</span> leap = date.isLeapYear(); <span class="comment">//false(not a leap year)</span></div><div class="line"> </div><div class="line"><span class="comment">//时间的解析和格式化</span></div><div class="line">LocalDate date = LocalDate.parse(“<span class="number">2017</span>-<span class="number">01</span>-<span class="number">21</span>”);</div><div class="line">LocalTime time = LocalTime.parse(“<span class="number">13</span>:<span class="number">45</span>:<span class="number">20</span>”);</div><div class="line"> </div><div class="line">LocalDateTime now = LocalDateTime.now();</div><div class="line">now.format(DateTimeFormatter.BASIC_ISO_DATE);</div><div class="line"> </div><div class="line"><span class="comment">//合并日期和时间</span></div><div class="line">LocalDateTime dt1 = LocalDateTime.of(<span class="number">2017</span>, Month.JANUARY, <span class="number">21</span>, <span class="number">18</span>, <span class="number">7</span>);</div><div class="line">LocalDateTime dt2 = LocalDateTime.of(localDate, time);</div><div class="line">LocalDateTime dt3 = localDate.atTime(<span class="number">13</span>,<span class="number">45</span>,<span class="number">20</span>);</div><div class="line">LocalDateTime dt4 = localDate.atTime(time);</div><div class="line">LocalDateTime dt5 = time.atDate(localDate);</div><div class="line"> </div><div class="line"><span class="comment">//操作日期</span></div><div class="line">LocalDate date1 = LocalDate.of(<span class="number">2014</span>,<span class="number">3</span>,<span class="number">18</span>); <span class="comment">//2014-3-18</span></div><div class="line">LocalDate date2 = date1.plusWeeks(<span class="number">1</span>); <span class="comment">//2014-3-25</span></div><div class="line">LocalDate date3 = date2.minusYears(<span class="number">3</span>); <span class="comment">//2011-3-25</span></div><div class="line">LocalDate date4 = date3.plus(<span class="number">6</span>, ChronoUnit.MONTHS); <span class="comment">//2011-09-25</span></div></pre></td></tr></table></figure>
<p>可以发现，新的时间和日期API都是不可变的，并且是线程安全的，之前使用的比如<code>SimpleDateFormat</code>不是线程安全的， 现在可以使用<code>DateTimeFormatter</code>来代替，<code>DateTimeFormatter</code>是线程安全的。</p>
<p>以上只是Java8提供的新时间和日期API的一部分，更多的内容可以参考官网文档，有了这些API，相信完全可以不再依赖开源的类库来进行时间的处理。</p>
<h2 id="小结"><a href="#小结" class="headerlink" title="小结"></a>小结</h2><p>以上只是对Java8的新特性进行了一个非常简单的介绍，由于近年来函数式编程很火，Java8也受函数式编程思想的影响，吸收了函数式编程好的地方， 很多新特性都是按照函数式编程来设计的。关于Java8还有非常多的细节没有提到，这些需要我们自行去学习，推荐一本学习Java8非常好的书籍——《Java8实战》， 看完这本书对Java8的使用可以有一个比较清楚的了解。</p>
<p>现在已经是2017年了，据说今年会推出Java9，Java9会推出什么新特性，让我们拭目以待吧。</p>

      
    </div>
    
  </div>
  
    
    <div class="copyright">
        <p><span>本文标题:</span><a href="/2017/04/26/java-8-in-practice/">Java8学习笔记</a></p>
        <p><span>文章作者:</span><a href="/" title="回到主页">xiaoyou</a></p>
        <p><span>发布时间:</span>2017-04-26, 08:50:00</p>
        <p><span>最后更新:</span>2017-04-26, 14:06:30</p>
        <p>
            <span>原始链接:</span><a class="post-url" href="/2017/04/26/java-8-in-practice/" title="Java8学习笔记">http://yoursite.com/2017/04/26/java-8-in-practice/</a>
            <span class="copy-path" data-clipboard-text="原文: http://yoursite.com/2017/04/26/java-8-in-practice/　　作者: xiaoyou" title="点击复制文章链接"><i class="fa fa-clipboard"></i></span>
            <script> var clipboard = new Clipboard('.copy-path'); </script>
        </p>
        <p>
            <span>许可协议:</span><i class="fa fa-creative-commons"></i> <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/" title="CC BY-NC-SA 4.0 International" target = "_blank">"署名-非商用-相同方式共享 4.0"</a> 转载请保留原文链接及作者。
        </p>
    </div>



    <nav id="article-nav">
        
            <div id="article-nav-newer" class="article-nav-title">
                <a href="/2017/04/23/distribute-micro-service-2/">
                    微服务业务开发三个难题－拆分、事务、查询（下）
                </a>
            </div>
        
        
            <div id="article-nav-older" class="article-nav-title">
                <a href="/2017/04/26/java-8-in-action/">
                    Java8 In Action
                </a>
            </div>
        
    </nav>

  
</article>

    <div id="toc" class="toc-article">
        <strong class="toc-title">文章目录</strong>
        
            <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#函数式接口"><span class="toc-number">1.</span> <span class="toc-text">函数式接口</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Lambda表达式和方法引用"><span class="toc-number">2.</span> <span class="toc-text">Lambda表达式和方法引用</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Stream"><span class="toc-number">3.</span> <span class="toc-text">Stream</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#默认方法"><span class="toc-number">4.</span> <span class="toc-text">默认方法</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Optional"><span class="toc-number">5.</span> <span class="toc-text">Optional</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#CompletableFuture"><span class="toc-number">6.</span> <span class="toc-text">CompletableFuture</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#新的时间和日期API"><span class="toc-number">7.</span> <span class="toc-text">新的时间和日期API</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#小结"><span class="toc-number">8.</span> <span class="toc-text">小结</span></a></li></ol>
        
    </div>
    <style>
        .left-col .switch-btn,
        .left-col .switch-area {
            display: none;
        }
        .toc-level-3 i,
        .toc-level-3 ol {
            display: none !important;
        }
    </style>

    <input type="button" id="tocButton" value="隐藏目录"  title="点击按钮隐藏或者显示文章目录">

    <script>
        yiliaConfig.toc = ["隐藏目录", "显示目录", !!"false"];
    </script>



    
<div class="share">
    
        <div class="bdsharebuttonbox">
            <a href="#" class="fa fa-twitter bds_twi" data-cmd="twi" title="分享到推特"></a>
            <a href="#" class="fa fa-weibo bds_tsina" data-cmd="tsina" title="分享到新浪微博"></a>
            <a href="#" class="fa fa-qq bds_sqq" data-cmd="sqq" title="分享给 QQ 好友"></a>
            <a href="#" class="fa fa-files-o bds_copy" data-cmd="copy" title="复制网址"></a>
            <a href="#" class="fa fa fa-envelope-o bds_mail" data-cmd="mail" title="通过邮件分享"></a>
            <a href="#" class="fa fa-weixin bds_weixin" data-cmd="weixin" title="生成文章二维码"></a>
            <a href="#" class="fa fa-share-alt bds_more" data-cmd="more"></i></a>
        </div>
        <script>
            window._bd_share_config={
                "common":{"bdSnsKey":{},"bdText":"Java8学习笔记　| Lost Youth　","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"24"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];
        </script>
    

    
</div>







    




    <div class="scroll" id="post-nav-button">
        
            <a href="/2017/04/23/distribute-micro-service-2/" title="上一篇: 微服务业务开发三个难题－拆分、事务、查询（下）">
                <i class="fa fa-angle-left"></i>
            </a>
        

        <a title="文章列表"><i class="fa fa-bars"></i><i class="fa fa-times"></i></a>

        
            <a href="/2017/04/26/java-8-in-action/" title="下一篇: Java8 In Action">
                <i class="fa fa-angle-right"></i>
            </a>
        
    </div>

    <ul class="post-list"><li class="post-list-item"><a class="post-list-link" href="/2017/05/20/distrute-in-action/">分布式服务化系统一致性的“最佳实干“</a></li><li class="post-list-item"><a class="post-list-link" href="/2017/05/12/spring-boot-in-action/">Spring Boot In Action</a></li><li class="post-list-item"><a class="post-list-link" href="/2017/05/04/mysql-youhua/">我必须得告诉大家的MySQL优化原理</a></li><li class="post-list-item"><a class="post-list-link" href="/2017/04/26/mysql-bizhibimui/">MySql 必知必会</a></li><li class="post-list-item"><a class="post-list-link" href="/2017/04/26/java-8-in-action/">Java8 In Action</a></li><li class="post-list-item"><a class="post-list-link" href="/2017/04/26/java-8-in-practice/">Java8学习笔记</a></li><li class="post-list-item"><a class="post-list-link" href="/2017/04/23/distribute-micro-service-1/">微服务业务开发三个难题－拆分、事务、查询（上）</a></li><li class="post-list-item"><a class="post-list-link" href="/2017/04/23/distribute-micro-service-2/">微服务业务开发三个难题－拆分、事务、查询（下）</a></li><li class="post-list-item"><a class="post-list-link" href="/2017/04/22/meituan-id/">Leaf——美团点评分布式ID生成系统</a></li><li class="post-list-item"><a class="post-list-link" href="/2017/04/10/rocket-in-practice-1/">RocketMQ实战（一）</a></li><li class="post-list-item"><a class="post-list-link" href="/2017/04/10/head-first-git-branch/">Git由浅入深之分支管理</a></li><li class="post-list-item"><a class="post-list-link" href="/2017/04/10/tomcat-principle/">Tomcat组成与工作原理</a></li><li class="post-list-item"><a class="post-list-link" href="/2017/04/10/tomcat-cluster/">Tomcat 集群实现源码级别剖析</a></li><li class="post-list-item"><a class="post-list-link" href="/2017/04/04/mysql-7-join/">Mysql的七种join</a></li><li class="post-list-item"><a class="post-list-link" href="/2017/04/04/hello-world/">Hello World</a></li></ul>




    <script>
        
    </script>
</div>
      <footer id="footer">
    <div class="outer">
        <div id="footer-info">
            <div class="footer-left">
                <i class="fa fa-copyright"></i> 
                2016-2017 xiaoyou
            </div>
            <div class="footer-right">
                <a href="http://hexo.io/" target="_blank" title="快速、简洁且高效的博客框架">Hexo</a>  Theme <a href="https://github.com/MOxFIVE/hexo-theme-yelee" target="_blank" title="简而不减 Hexo 双栏博客主题  v3.5">Yelee</a> by MOxFIVE <i class="fa fa-heart animated infinite pulse"></i>
            </div>
        </div>
        
            <div class="visit">
                
                    <span id="busuanzi_container_site_pv" style='display:none'>
                        <span id="site-visit" title="本站到访数"><i class="fa fa-user" aria-hidden="true"></i><span id="busuanzi_value_site_uv"></span>
                        </span>
                    </span>
                
                
                    <span>| </span>
                
                
                    <span id="busuanzi_container_page_pv" style='display:none'>
                        <span id="page-visit"  title="本页阅读量"><i class="fa fa-eye animated infinite pulse" aria-hidden="true"></i><span id="busuanzi_value_page_pv"></span>
                        </span>
                    </span>
                
            </div>
        
    </div>
</footer>
    </div>
    
<script data-main="/js/main.js" src="//cdn.bootcss.com/require.js/2.2.0/require.min.js"></script>

    <script>
        $(document).ready(function() {
            var iPad = window.navigator.userAgent.indexOf('iPad');
            if (iPad > -1 || $(".left-col").css("display") === "none") {
                var bgColorList = ["#9db3f4", "#414141", "#e5a859", "#f5dfc6", "#c084a0", "#847e72", "#cd8390", "#996731"];
                var bgColor = Math.ceil(Math.random() * (bgColorList.length - 1));
                $("body").css({"background-color": bgColorList[bgColor], "background-size": "cover"});
            }
            else {
                var backgroundnum = 5;
                var backgroundimg = "url(/background/bg-x.jpg)".replace(/x/gi, Math.ceil(Math.random() * backgroundnum));
                $("body").css({"background": backgroundimg, "background-attachment": "fixed", "background-size": "cover"});
            }
        })
    </script>





<div class="scroll" id="scroll">
    <a href="#" title="返回顶部"><i class="fa fa-arrow-up"></i></a>
    <a href="#comments" onclick="load$hide();" title="查看评论"><i class="fa fa-comments-o"></i></a>
    <a href="#footer" title="转到底部"><i class="fa fa-arrow-down"></i></a>
</div>
<script>
    // Open in New Window
    
        var oOpenInNew = {
            
            
            
            
            
            
             archives: ".archive-article-title", 
             miniArchives: "a.post-list-link", 
            
             friends: "#js-friends a", 
             socail: ".social a" 
        }
        for (var x in oOpenInNew) {
            $(oOpenInNew[x]).attr("target", "_blank");
        }
    
</script>

<script async src="https://dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js">
</script>
  </div>
</body>
</html>